package com.dkm.orproject.dkmoa.service.serviceimpl.flow.overtime;

import com.dkm.orproject.dkmoa.dao.*;
import com.dkm.orproject.dkmoa.domain.*;
import com.dkm.orproject.dkmoa.service.flow.overtime.OaBatchOvertimeFlowService;
import com.dkm.orproject.utils.utils.IdToobtainUtils;
import com.github.pagehelper.PageHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName : OaBatchOvertimeFlowServiceImpl  //类名
 * @Description : 加班流程服务接口实现类  //描述
 * @Author : 易嵘  //作者
 * @Date: 2020-11-03 09:35  //时间
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class OaBatchOvertimeFlowServiceImpl implements OaBatchOvertimeFlowService {

    /**
     * 流程记录
     */
    OaFlowSchedule flowSchedule;

    /**
     * 流程记录日志
     */
    @Resource
    OaFlowScheduleMapper flowScheduleMapper;

    /**
     * 部门Mapper
     */
    @Resource
    OaDepartmentMapper departmentMapper;

    /**
     * 通知人员关联Mapper
     */
    @Resource
    OaInformMapper informMapper;

    /**
     * 通知Mapper
     */
    @Resource
    OaMessageMapper messageMapper;
    /**
     * 人员Mapper
     */
    @Resource
    OaPersonnelMapper personnelMapper;
    /**
     * 起草节点
     */
    static Long START_NODE = 773569671428452352L;

    /**
     * 部门审核节点id
     */
    static final Long AUDIT_SECTION_NODE = 773569851229876224L;


    /**
     * 人事审核节点id
     */
    static final Long AUDIT_STAFFING_NODE = 773569931420774400L;

    /**
     * 总经理审核节点id
     */
    static final Long EX_STAFFING_NODE = 773570005534126080L;

    /**
     * 结束节点id
     */
    static final Long OVER_NODE = 766232301880356864L;

    /**
     * 人事审核
     */
    static final String OVERTIME_STAFFING_CHECK_INFORM="OVERTIME_STAFFING_CHECK_INFORM";

    /**
     * 领导审核
     */
    static final String OVERTIME_EX_CHECK_INFORM="OVERTIME_EX_CHECK_INFORM";

    /**
     * id生成工具
     */
    @Resource
    IdToobtainUtils idToobtainUtils;

    /**
     * 加班流程Mapper
     */
    @Resource
    OaBatchOvertimeFlowMapper batchOvertimeFlowMapper;

    /**
     * 分页查询
     * @param batchOvertimeName 加班流程名称
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param page 当前页数
     * @param limit 显示行数
     * @return 查询结果
     */
    @Override
    public List<OaBatchOvertimeFlow> findAll(String batchOvertimeName, String startTime, String endTime, Integer page, Integer limit) {
        PageHelper.startPage(page,limit);
        return batchOvertimeFlowMapper.findAll(batchOvertimeName,startTime,endTime);
    }

    /**
     * 总行数
     * @param batchOvertimeName 加班流程名称
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 总行数
     */
    @Override
    public Long rowCount(String batchOvertimeName, String startTime, String endTime) {
        return batchOvertimeFlowMapper.rowCount(batchOvertimeName,startTime,endTime);
    }

    /**
     * id查询
     * @param id 加班流程id
     * @return 回调函数
     */
    @Override
    public OaBatchOvertimeFlow findById(Long id) {
        return batchOvertimeFlowMapper.selectByPrimaryKey(id);
    }

    /**
     * id删除
     * @param id 加班流程id
     * @return 回调函数
     */
    @Override
    public int deleteById(Long id) {
        messageMapper.deleteByFormId(id);
        return batchOvertimeFlowMapper.deleteByPrimaryKey(id);
    }

    /**
     * 起草人节点
     * @param batchOvertimeFlow 加班流程起草节点数据
     * @param personnel 操作人
     * @return 回调函数
     */
    @Override
    public int add(OaBatchOvertimeFlow batchOvertimeFlow, OaPersonnel personnel) {
        //流程节点 部门审核阶段
        batchOvertimeFlow.setBatchOvertimeSchedule(AUDIT_SECTION_NODE);
        //流程进度 设置流程进度 D部门审核
        batchOvertimeFlow.setIsRevision("D");
        //人员id
        batchOvertimeFlow.setPersonnelId(personnel.getPkPersonnelId());
        int row;
        //判断是新增还是修改
        if(ObjectUtils.isEmpty(batchOvertimeFlow.getPkBatchOvertimeId())){
            //加班流程id
            batchOvertimeFlow.setPkBatchOvertimeId(idToobtainUtils.getNumberId());
            //加班流程名称
            batchOvertimeFlow.setBatchOvertimeName(personnel.getPersonnelName()+"的加班流程");
            //操作人名称
            batchOvertimeFlow.setCreatedBy(personnel.getPersonnelName());
            //新增加班流程
            batchOvertimeFlowMapper.insertSelective(batchOvertimeFlow);
        }else{
            //修改加班流程
            batchOvertimeFlowMapper.updateByPrimaryKeySelective(batchOvertimeFlow);
        }

        //新建流程记录和通知信息
        OaMessage message = addFlowSchedule(START_NODE,batchOvertimeFlow.getPkBatchOvertimeId(),batchOvertimeFlow.getBatchOvertimeName(),personnel,"2");

        //查询部门领导
        Long personnelId = departmentMapper.selectByPrimaryKey(personnel.getPkDepartmentId()).getPersonnelId();
        //新增关联
        row=addInform(personnelId,message.getPkMessageId());
        return row;
    }

    /**
     * 关联通知
     * @param personnelId 通知人id
     * @param messageId 通知信息
     * @return 回调函数
     */
    private int addInform(Long personnelId,Long messageId){
        // 新建通知关联
        OaInform inform = new OaInform();
        // 通知关联id
        inform.setFkInformId(idToobtainUtils.getNumberId());
        // 设置为未读
        inform.setIsState("0");
        // 通知id
        inform.setMessageId(messageId);
        // 人员id
        inform.setPersonnelId(personnelId);

        // 新增通知关联集合
        return informMapper.insertSelective(inform);
    }

    /**
     * 批量关联通知
     * @param personnelIds 通知人id集合
     * @param messageId 通知信息
     * @return 回调函数
     */
    private int addInform(List<Long> personnelIds,Long messageId){
        int row=0;
        if(personnelIds== null || personnelIds.size()<1){
            return row;
        }
        // 通知人员关联集合
        List<OaInform> informs = new ArrayList<>();
        for (Long personnelId : personnelIds) {
            // 新建通知关联
            OaInform inform = new OaInform();
            // 通知关联id
            inform.setFkInformId(idToobtainUtils.getNumberId());
            // 设置为未读
            inform.setIsState("0");
            // 通知id
            inform.setMessageId(messageId);
            // 人员id
            inform.setPersonnelId(personnelId);
            informs.add(inform);
        }
        row=informMapper.insertAll(informs);
        // 新增通知关联集合
        return row;
    }

    /**
     * 新增流程记录 和通知信息
     * @param flowId 流程id
     * @param formId 表单id
     * @param flowName 流程名称
     * @param personnel 操作人
     * @return 通知信息
     */
    private OaMessage addFlowSchedule(Long flowId,Long formId,String flowName,OaPersonnel personnel,String formReason,String number){
        // 流程记录
        flowSchedule = new OaFlowSchedule();
        // 流程记录id
        flowSchedule.setPkFlowScheduleId(idToobtainUtils.getNumberId());
        // 离职流程id  起草节点
        flowSchedule.setFlowId(flowId);
        // 绑定表单
        flowSchedule.setFormId(formId);
        // 人员id
        flowSchedule.setPersonnelId(personnel.getPkPersonnelId());
        // 不通过原因
        flowSchedule.setFormReason(formReason);
        //审核人
        flowSchedule.setCreatedBy(personnel.getPersonnelName());
        // 新增转正流程记录
        flowScheduleMapper.insertSelective(flowSchedule);

        //删除旧通知
        int row=messageMapper.deleteByFormId(flowId);
        // 新建通知
        OaMessage message = new OaMessage();
        //通知id
        message.setPkMessageId(idToobtainUtils.getNumberId());
        //创建人
        message.setCreatedBy(personnel.getPersonnelName());
        //流程id
        message.setFormId(formId);
        // 通知标题
        message.setMessageName(flowName);
        //状态 2 待办
        message.setIsRevision(number);
        // 链接地址
        message.setMessageUrl("pages/dkmoa/front/flow/overtime/overtimeAddorUpdate.html?pkBatchOvertimeId=");
        // 新增通知
        messageMapper.insertSelective(message);

        return message;
    }

    /**
     * 新增流程记录 和通知信息
     * @param flowId 流程id
     * @param formId 表单id
     * @param flowName 流程名称
     * @param personnel 操作人
     * @return 通知信息
     */
    private OaMessage addFlowSchedule(Long flowId,Long formId,String flowName,OaPersonnel personnel,String number){
        // 流程记录
        flowSchedule = new OaFlowSchedule();
        // 流程记录id
        flowSchedule.setPkFlowScheduleId(idToobtainUtils.getNumberId());
        // 离职流程id  起草节点
        flowSchedule.setFlowId(flowId);
        // 绑定表单
        flowSchedule.setFormId(formId);
        // 人员id
        flowSchedule.setPersonnelId(personnel.getPkPersonnelId());
        // 通过原因
        flowSchedule.setFormReason("  ");
        //审核人
        flowSchedule.setCreatedBy(personnel.getPersonnelName());
        // 新增转正流程记录
        flowScheduleMapper.insertSelective(flowSchedule);

        //删除旧通知
        int row=messageMapper.deleteByFormId(formId);
        // 新建通知
        OaMessage message = new OaMessage();
        //通知id
        message.setPkMessageId(idToobtainUtils.getNumberId());
        //创建人
        message.setCreatedBy(personnel.getPersonnelName());
        //流程id
        message.setFormId(formId);
        // 通知标题
        message.setMessageName(flowName);
        //状态 2 待办
        message.setIsRevision(number);
        // 链接地址
        message.setMessageUrl("pages/dkmoa/front/flow/overtime/overtimeAudit.html?pkBatchOvertimeId=");
        // 新增通知
        messageMapper.insertSelective(message);

        return message;
    }

    /**
     * 部门领导审核通过
     * @param departmentOpinion 通过意见
     * @param personnel 操作人
     * @param pkBatchOvertimeId 加班流程id
     * @return 回调函数
     */
    @Override
    public int sectionPass(String departmentOpinion, OaPersonnel personnel, Long pkBatchOvertimeId) {
        //id查询
        OaBatchOvertimeFlow batchOvertimeFlow=batchOvertimeFlowMapper.selectByPrimaryKey(pkBatchOvertimeId);
        //赋值部门领导审核意见
        batchOvertimeFlow.setDepartmentOpinion(departmentOpinion);

        batchOvertimeFlow.setBatchOvertimeSchedule(AUDIT_STAFFING_NODE);
        //流程进度 设置流程进度 R人事审核
        batchOvertimeFlow.setIsRevision("R");
        //修改部门领导审核意见
        int row=batchOvertimeFlowMapper.updateByPrimaryKeySelective(batchOvertimeFlow);
        //新增通知信息
        OaMessage message=addFlowSchedule(AUDIT_SECTION_NODE,pkBatchOvertimeId,batchOvertimeFlow.getBatchOvertimeName(),personnel,"4");

        // 根据通知权限代码通知人事领导
        List<Long> personnelIds = personnelMapper.selectByHover(OVERTIME_STAFFING_CHECK_INFORM);
        addInform(personnelIds,message.getPkMessageId());
        return row;
    }

    /**
     * 部门领导不同意
     * @param pkBatchOvertimeId 流程id
     * @param personnel 操作人
     * @param formReason 不通过原因
     * @return
     */
    @Override
    public int sectionNoPass(Long pkBatchOvertimeId, OaPersonnel personnel, String formReason)  {
        //id查询
        OaBatchOvertimeFlow batchOvertimeFlow=batchOvertimeFlowMapper.selectByPrimaryKey(pkBatchOvertimeId);
        //流程进度 设置流程进度 C起草人
        batchOvertimeFlow.setIsRevision("C");
        //起草节点
        batchOvertimeFlow.setBatchOvertimeSchedule(START_NODE);
        //修改为起草阶段
        int row=batchOvertimeFlowMapper.updateByPrimaryKeySelective(batchOvertimeFlow);
        //新增通知信息
        OaMessage message=addFlowSchedule(AUDIT_SECTION_NODE,pkBatchOvertimeId,batchOvertimeFlow.getBatchOvertimeName(),personnel,formReason,"2");
        //通知起草人
        addInform(batchOvertimeFlow.getPersonnelId(),message.getPkMessageId());
        return row;
    }

    /**
     * 人事同意
     * @param pkBatchOvertimeId 加班流程id
     * @param personnelOpinion  人事通过意见
     * @param personnel 操作人
     * @return 回调函数
     */
    @Override
    public int staffingPass(Long pkBatchOvertimeId,String personnelOpinion, OaPersonnel personnel) {
        //id查询
        OaBatchOvertimeFlow batchOvertimeFlow=batchOvertimeFlowMapper.selectByPrimaryKey(pkBatchOvertimeId);
        //赋值人事领导审核意见
        batchOvertimeFlow.setPersonnelOpinion(personnelOpinion);
        //流程进度 设置流程进度 E总经理审核
        batchOvertimeFlow.setIsRevision("E");

        batchOvertimeFlow.setBatchOvertimeSchedule(EX_STAFFING_NODE);
        //修改人事领导审核意见
        int row=batchOvertimeFlowMapper.updateByPrimaryKeySelective(batchOvertimeFlow);
        //新增通知信息
        OaMessage message=addFlowSchedule(AUDIT_STAFFING_NODE,pkBatchOvertimeId,batchOvertimeFlow.getBatchOvertimeName(),personnel,"2");

        // 根据通知权限代码通知总经理
        List<Long> personnelIds = personnelMapper.selectByHover(OVERTIME_EX_CHECK_INFORM);
        //关联通知信息
        addInform(personnelIds,message.getPkMessageId());
        return row;
    }

    /**
     * 人事不同意
     * @param pkBatchOvertimeId
     * @param personnel
     * @param formReason
     * @return
     */
    @Override
    public int staffingNoPass(Long pkBatchOvertimeId, OaPersonnel personnel, String formReason) {
        //id查询
        OaBatchOvertimeFlow batchOvertimeFlow=batchOvertimeFlowMapper.selectByPrimaryKey(pkBatchOvertimeId);
        //流程进度 设置流程进度 C起草人
        batchOvertimeFlow.setIsRevision("C");
        batchOvertimeFlow.setBatchOvertimeSchedule(START_NODE);
        //修改为起草阶段
        int row=batchOvertimeFlowMapper.updateByPrimaryKeySelective(batchOvertimeFlow);
        //新增通知信息
        OaMessage message=addFlowSchedule(AUDIT_STAFFING_NODE,pkBatchOvertimeId,batchOvertimeFlow.getBatchOvertimeName(),personnel,formReason,"2");
        //通知起草人
        addInform(batchOvertimeFlow.getPersonnelId(),message.getPkMessageId());
        return row;
    }

    /**
     * 批量查询
     * @param list 加班id集合
     * @return 查询结果
     */
    @Override
    public List<OaRegularFlow> selectAll(List<Long> list) {

        return batchOvertimeFlowMapper.selectAll(list);
    }

    /**
     * 批量删除
     * @param list 加班id集合
     * @return 回调函数
     */
    @Override
    public int deleteAll(List<Long> list) {
        messageMapper.deleteAllFormId(list);
        return batchOvertimeFlowMapper.deleteAll(list);
    }

    /**
     * 总经理审核通过
     * @param pkBatchOvertimeId 加班流程id
     * @param managerOpinion 总经理意见
     * @param personnel 操作人
     * @return 回调函数
     */
    @Override
    public int exPass(Long pkBatchOvertimeId, String managerOpinion, OaPersonnel personnel) {
        //id查询
        OaBatchOvertimeFlow batchOvertimeFlow=batchOvertimeFlowMapper.selectByPrimaryKey(pkBatchOvertimeId);
        //赋值总经理审核意见
        batchOvertimeFlow.setManagerOpinion(managerOpinion);
        //流程节点设置为结束节点
        batchOvertimeFlow.setBatchOvertimeSchedule(OVER_NODE);
        //流程进度 设置流程进度 1流程完成
        batchOvertimeFlow.setIsRevision("1");
        //修改人事领导审核意见
        int row= batchOvertimeFlowMapper.updateByPrimaryKeySelective(batchOvertimeFlow);
        //新增通知信息
        OaMessage message=addFlowSchedule(EX_STAFFING_NODE,pkBatchOvertimeId,batchOvertimeFlow.getBatchOvertimeName(),personnel,"4");
        // 流程记录
        flowSchedule = new OaFlowSchedule();
        // 流程记录id
        flowSchedule.setPkFlowScheduleId(idToobtainUtils.getNumberId());
        // 离职流程id  起草节点
        flowSchedule.setFlowId(OVER_NODE);
        // 绑定表单
        flowSchedule.setFormId(pkBatchOvertimeId);
        // 人员id
        flowSchedule.setPersonnelId(personnel.getPkPersonnelId());
        // 通过原因
        flowSchedule.setFormReason("  ");
        //审核人
        flowSchedule.setCreatedBy(personnel.getPersonnelName());
        // 新增转正流程记录
        flowScheduleMapper.insertSelective(flowSchedule);

        //关联通知信息
        addInform(batchOvertimeFlow.getPersonnelId(),message.getPkMessageId());
        return row;
    }

    /**
     * 总经理审核不通过
     * @param pkBatchOvertimeId 加班流程id
     * @param formReason 总经理意见
     * @param personnel 操作人
     * @return 回调函数
     */
    @Override
    public int exNoPass(Long pkBatchOvertimeId, String formReason, OaPersonnel personnel) {
        //id查询
        OaBatchOvertimeFlow batchOvertimeFlow=batchOvertimeFlowMapper.selectByPrimaryKey(pkBatchOvertimeId);
        //流程进度 设置流程进度 C起草人
        batchOvertimeFlow.setIsRevision("C");
        batchOvertimeFlow.setBatchOvertimeSchedule(START_NODE);
        //修改为起草阶段
        int row=batchOvertimeFlowMapper.updateByPrimaryKeySelective(batchOvertimeFlow);
        //新增通知信息
        OaMessage message=addFlowSchedule(EX_STAFFING_NODE,pkBatchOvertimeId,batchOvertimeFlow.getBatchOvertimeName(),personnel,formReason,"2");
        //通知起草人
        addInform(batchOvertimeFlow.getPersonnelId(),message.getPkMessageId());
        return row;
    }
}
